﻿using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TrinityAPI.Base.Tools;

namespace TrinityAPI.Base.Models
{
    public class CacheManager
    {
        private int _expires;
        private string _key;
        private ICache _cache;

        public string Key
        {
            get { return _key; }
        }
        public ICache Cache
        {
            get { return _cache; }
        }

        public CacheManager(string key, ICache cache) : this(key, cache, 0)
        {
        }

        public CacheManager(string key, ICache cache, int expires)
        {
            _expires = expires;
            _key = key;
            _cache = cache;
        }

        public T Get<T>()
        {
            return JSONHelper.DeserializeObject<T>(_cache.Get(_key) as string);
        }

        public void Set(object data)
        {
            if (data != null)
            {
                if (_expires > 0)
                    _cache.Set(_key, data is String ? data : JSONHelper.SerializeObject(data), _expires);
                else
                    _cache.Set(_key, data is String ? data : JSONHelper.SerializeObject(data));
            }
        }

        public void Remove()
        {
            _cache.Remove(_key);
        }

        public void Clear()
        {
            _cache.RemoveAll();
        }

        public static CacheManager Init(JObject config, JObject connections, JObject dataset, string parentPath)
        {
            if (config != null)
            {
                string key = Utils.ParseObject(config.GetNecessaryJsonObjectStringValue("key", parentPath), dataset)?.ToString();
                if (string.IsNullOrWhiteSpace(key))
                    throw new ConfigException("{0}.key is not a valid value", parentPath);
                bool absolutekey = config.GetJsonObjectBooleanValue("absolutekey");
                var expires = Utils.ParseObject(config.GetJsonObjectValue("expires"), dataset);
                var connid = config.GetNecessaryJsonObjectStringValue("connid", parentPath);
                var connection = connections.GetNecessaryJsonObject(connid, "constant.connection");

                int expireSeconds = 0;
                if (expires != null)
                {
                    if (expires.Type != JTokenType.Integer && expires.Type != JTokenType.Float)
                        throw new ConfigException("The data type of {0}.expires mast be number", parentPath);
                    expireSeconds = expires.Value<int>();
                }

                if (!absolutekey) //key非绝对缓存路径，加上接口名称，避免key冲突，相互覆盖
                    key = $"{APIContext.ApiFullName}_{key}";

                var cacheManager = Utils.GetCacheAdapter(connid, connection);
                return new CacheManager(key.ToUpper(), cacheManager, expireSeconds);
            }
            return null;
        }
    }
}
